package com.jswdwsx.common.utils;

import org.springframework.util.StringUtils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

public class DateTimeUtils {

    public final static ZoneId DEFAULT_ZONE_ID = ZoneId.of("Pacific/Auckland");
    public final static ZoneId BEIJING_ZONE_ID = ZoneId.of("Asia/Shanghai");

    public final static Long HOURS_OF_24 = 86400L;
    public final static Long END_OFFSET = 86399L;
    public final static String START_TIME = "00:00:00";
    public final static String MIDDLE_TIME = "12:00:00";
    public final static String END_TIME = "23:59:59";
    public final static DateTimeFormatter FORMAT_YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public final static DateTimeFormatter FORMAT_YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public final static DateTimeFormatter FORMAT_YYYYMMDDHHMMSS = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");


    /**
     * 获取当前秒数
     *
     * @return 当前秒数
     */
    public static Long getNowEpochSecond() {
        return Instant.now().getEpochSecond();
    }

    /**
     * 获取当前默认时区时间
     *
     * @return 当前默认时区时间
     */
    public static ZonedDateTime getNowZonedDateTime() {
        return ZonedDateTime.now(DEFAULT_ZONE_ID);
    }

    /**
     * 获取指定日期的起始秒
     *
     * @param date   指定日期字符串
     * @param zoneId 指定时区
     * @return 指定日期的起始秒
     */
    public static Long toEpochSecondStart(String date, ZoneId zoneId) {
        return ZonedDateTime.of(LocalDate.parse(date), LocalTime.parse(START_TIME), zoneId != null ? zoneId : DEFAULT_ZONE_ID).toEpochSecond();
    }

    /**
     * 获取指定日期的起始秒
     *
     * @param date 指定日期字符串
     * @return 指定日期的起始秒
     */
    public static Long toEpochSecondStart(String date) {
        return toEpochSecondStart(date, DEFAULT_ZONE_ID);
    }

    public static Long toEpochSecondMiddle(String date, ZoneId zoneId) {
        return ZonedDateTime.of(LocalDate.parse(date), LocalTime.parse(MIDDLE_TIME), zoneId != null ? zoneId : DEFAULT_ZONE_ID).toEpochSecond();
    }

    public static Long toEpochSecondMiddle(String date) {
        return toEpochSecondMiddle(date, DEFAULT_ZONE_ID);
    }

    /**
     * 获取指定日期的结束秒
     *
     * @param date 指定日期字符串
     * @return 指定日期的结束秒
     */
    public static Long toEpochSecondEnd(String date, ZoneId zoneId) {
        return ZonedDateTime.of(LocalDate.parse(date), LocalTime.parse(END_TIME), zoneId != null ? zoneId : DEFAULT_ZONE_ID).toEpochSecond();
    }

    public static Long toEpochSecondEnd(String date) {
        return toEpochSecondEnd(date, DEFAULT_ZONE_ID);
    }

    //

    public static Long toEpochSecond(String date, String time, ZoneId zoneId) {
        return ZonedDateTime.of(LocalDate.parse(date), LocalTime.parse(time), zoneId != null ? zoneId : DEFAULT_ZONE_ID).toEpochSecond();
    }

    public static Long toEpochSecond(String date, String time) {
        return toEpochSecond(date, time, null);
    }

    public static Long toEpochSecondWithDataTime(String dateTime, ZoneId zoneId) {
        return ZonedDateTime.of(LocalDateTime.parse(dateTime.replace(' ', 'T')), zoneId != null ? zoneId : DEFAULT_ZONE_ID).toEpochSecond();
    }

    //

    public static ZonedDateTime fromEpochSecond(Long epochSecond, ZoneId zoneId) {
        return ZonedDateTime.ofInstant(
                Instant.ofEpochSecond(epochSecond != null ? epochSecond : getNowEpochSecond()),
                zoneId != null ? zoneId : DEFAULT_ZONE_ID
        );
    }

    public static ZonedDateTime fromEpochSecond(Long epochSecond) {
        return fromEpochSecond(epochSecond, null);
    }

    public static ZonedDateTime fromEpochSecond() {
        return fromEpochSecond(null, null);
    }

    //

    public static String formatByYYYYMMDD(Long epochSecond) {
        return fromEpochSecond(epochSecond, null).format(FORMAT_YYYY_MM_DD);
    }

    public static String formatByYYYYMMDDHHMMSS(Long epochSecond) {
        return fromEpochSecond(epochSecond, null).format(FORMAT_YYYY_MM_DD_HH_MM_SS);
    }

    public static String getCurrentDateTimeString() {
        return formatByYYYYMMDDHHMMSS(getNowEpochSecond());
    }

    public static String getCurrentDateTimeStringDYYYYMMDDHHMMSS() {
        return ZonedDateTime.now(DEFAULT_ZONE_ID).format(FORMAT_YYYYMMDDHHMMSS);
    }

    public static Long toEpochSecondOfPattern(String date, String pattern) {
        if (StringUtils.hasText(date)) {
            return ZonedDateTime.of(LocalDate.parse(date, DateTimeFormatter.ofPattern(pattern)), LocalTime.parse(END_TIME), DEFAULT_ZONE_ID).toEpochSecond();
        }
        return null;
    }

    /**
     * 获取本月第一秒
     *
     * @return 本月第一秒
     */
    public static Long getMonthStart() {
        ZonedDateTime nowZonedDateTime = getNowZonedDateTime();
        return getMonthStart(nowZonedDateTime);
    }

    public static Long getMonthStart(ZonedDateTime nowZonedDateTime) {
        ZonedDateTime zonedDateTime = nowZonedDateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
        return zonedDateTime.toEpochSecond();
    }

    /**
     * 获取本月最后一秒
     *
     * @return 本月最后一秒
     */
    public static Long getMonthEnd() {
        ZonedDateTime nowZonedDateTime = getNowZonedDateTime();
        return getMonthEnd(nowZonedDateTime);
    }

    public static Long getMonthEnd(ZonedDateTime nowZonedDateTime) {
        ZonedDateTime zonedDateTime = nowZonedDateTime.plusMonths(1).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
        return zonedDateTime.toEpochSecond() - 1;
    }

    public static Long getNowMonth() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        //设置为15号,当前日期既为本月第15天
        c.set(Calendar.DAY_OF_MONTH, 15);
        //将小时至0
        c.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        c.set(Calendar.MINUTE, 0);
        //将秒至0
        c.set(Calendar.SECOND, 0);
        //将毫秒至0
        c.set(Calendar.MILLISECOND, 0);
        return c.getTimeInMillis() / 1000;
    }

    public static Long getStartMonth(Long time) {
        //将开始月份设置为该月的第0秒
        Calendar startC = Calendar.getInstance();
        startC.setTime(new Date(time * 1000));
        startC.set(Calendar.DAY_OF_MONTH, 1);
        //将小时至0
        startC.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        startC.set(Calendar.MINUTE, 0);
        //将秒至0
        startC.set(Calendar.SECOND, 0);
        //将毫秒至0
        startC.set(Calendar.MILLISECOND, 0);
        return startC.getTimeInMillis() / 1000;
    }

    public static Long getEndMonth(Long time) {
        //将结束月份设置为下一个月的第0秒
        Calendar endC = Calendar.getInstance();
        endC.setTime(new Date(time * 1000));
        endC.add(Calendar.MONTH, 1);
        endC.set(Calendar.DAY_OF_MONTH, 1);
        //将小时至0
        endC.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        endC.set(Calendar.MINUTE, 0);
        //将秒至0
        endC.set(Calendar.SECOND, 0);
        //将毫秒至0
        endC.set(Calendar.MILLISECOND, 0);
        return endC.getTimeInMillis() / 1000;
    }

    public static Long getLastStartMonth(Long time) {
        Calendar startC = Calendar.getInstance();
        startC.setTime(new Date(time * 1000));
        startC.add(Calendar.MONTH, -1);
        startC.set(Calendar.DAY_OF_MONTH, 1);
        startC.set(Calendar.HOUR_OF_DAY, 0);
        startC.set(Calendar.MINUTE, 0);
        startC.set(Calendar.SECOND, 0);
        startC.set(Calendar.MILLISECOND, 0);
        return startC.getTimeInMillis() / 1000;
    }

    public static String getBeijingYYYYMMDDHHMMSS() {
        return ZonedDateTime.now(BEIJING_ZONE_ID).format(FORMAT_YYYYMMDDHHMMSS);
    }

    public static String getDateTimeString(Long epochSecond, String timeZoneId, String pattern) {
        return ZonedDateTime.ofInstant(
                Instant.ofEpochSecond(epochSecond),
                ZoneId.of(timeZoneId)
        ).format(DateTimeFormatter.ofPattern(pattern));
    }
}
